package io.jpress.commons.utils;

import com.jfinal.kit.Base64Kit;
import com.jfinal.kit.LogKit;

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class RsaUtil {


    /**
     * 生成密钥对
     *
     * @return
     * @throws Exception
     */
    public static KeyPair getKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        //《2015 年加密宣言》密码指南建议，RSA 算法使用的密钥长度至少应为 2048 位。
        keyPairGenerator.initialize(2048);
        return keyPairGenerator.generateKeyPair();
    }

    /**
     * 公钥字符串转PublicKey实例
     *
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static PublicKey getPublicKey(String publicKey) throws Exception {
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKey.getBytes());
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(keySpec);
    }

    /**
     * 私钥字符串转PrivateKey实例
     *
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String privateKey) throws Exception {
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKey.getBytes());
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);
    }

    /**
     * 公钥加密
     *
     * @param content
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublicKey(byte[] content, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(content);
    }

    /**
     * 私钥加密
     *
     * @param content
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPrivateKey(byte[] content, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        return cipher.doFinal(content);
    }


    /**
     * 私钥解密
     *
     * @param content
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] content, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(content);
    }


    /**
     * 公钥解密
     *
     * @param content
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static byte[] decrypByPublicKey(byte[] content, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        return cipher.doFinal(content);
    }


    public static void main(String[] args) {
        try {
            KeyPair keyPair = getKeyPair();
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();


            System.out.println("publicKey: " + Base64Kit.encode(publicKey.getEncoded()));
            System.out.println("-----------");
            System.out.println("privateKey: " + Base64Kit.encode(privateKey.getEncoded()));
            System.out.println("-----------");

            System.out.println("");

            String content = "123";
            byte[] bytes = encryptByPublicKey(content.getBytes("utf-8"), publicKey);
            System.out.println("publicKey加密" + content + ": " + Base64Kit.encode(bytes));
            System.out.println("-----------");
            byte[] dbytes = decryptByPrivateKey(bytes, privateKey);
            System.out.println(new String(dbytes, "utf-8"));

//            PublicKey publicKey = getPublicKey("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzjrJFHfITFqnETlkqz2qwdDzj/lPTeY0zBude+983+8U8Jpdp5XUK2P2F3RLA2DUlgiD5b1iR8bLA7jl2wCREpELlCFV16SuMZRdgxaypUd6EjcvbUKdBF4a6F1JfiacdPAehw5edvwQdMU2HTVIzr1XgG7BhXJsTuBm8f8bLBwIDAQAB");
//            byte[] bytes1 = encryptByPublicKey("123456".getBytes(), publicKey);
//            System.out.println(Base64Kit.encode(bytes1));
//            System.out.println(Base64.getEncoder().encodeToString(bytes1));
//
//            String dString = "X4dRZ+Cu7Yt/Qii+B/k0tQ/cfSVDSEXd8Jl+Tn2pX4eovF1p43U/FKWEgi+8FFNarhR9fB7cQODa4c9KHlLq7iXj1pB7ffu94BjMUNOjvOAkqjLkvEj8P8NrQQSkatgV9HjhAr6wk5g+zlZToLEWCU7TwBcs716ZN53loK9RXb8=";
//            PrivateKey privateKey = getPrivateKey("MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALOOskUd8hMWqcROWSrParB0POP+U9N5jTMG51773zf7xTwml2nldQrY/YXdEsDYNSWCIPlvWJHxssDuOXbAJESkQuUIVXXpK4xlF2DFrKlR3oSNy9tQp0EXhroXUl+Jpx08B6HDl52/BB0xTYdNUjOvVeAbsGFcmxO4Gbx/xssHAgMBAAECgYBBtVOZpYbD44RG2WEaIINrhW4PBTBJ8G5yoPEkukmKpDEefQTl9NlrGdNVHHzTY4u3aTKF9XBVID0JC2SuB0x90S1b29jUU6rUIlcaHamaToBvCG8aVFDyfLUkCQHe4coOiV3lLy0fKd+wsnjBaO8nvW1M3LsI5Sd8Po1oiz6MUQJBANiknQzkdIDC64KHRIYdAMVoghbUpXDRthV3Na8NzTTT4bm/QDMU1ukc8TJ4Iijl3KNcZpczN8CisZ3cUFX+vmkCQQDULVjzt3QbmGXSnPUOFtDXv8NJDerEGXyPD3ouB8BEJFepuuYl99ZbHnKVFwAKEAAx7n+cuHOBQl9phWiR1+/vAkEAyvAQyfXriH6O/LvXncXnZgTK77YMsA1SgvMjj7LfCmB8r3IPIoqf8siQzJUqcqM4NrMkyvhIfqQou9aYTqYOGQJBAMeoXHoKeaG2CKrls9usMJ20/6jxBae+a+2bHNfPx2bX4/39t7CmxPk9b4lH+Wt+nxBdY4wwLdDGik4bkckbr9UCQQCPs2k7fk8h0Sfq7ihu28iZw4LBAcuCbKCaO7jJcIIkJbBGSmjIwDS9PIeBPSKDaKmfeh1xHbT5cyZH2CE6fKit");
//
//            byte[] bytes = decryptByPrivateKey(dString.getBytes(), privateKey);
//            System.out.println(new String(bytes));

        } catch (Exception e) {
            LogKit.error(e.toString(), e);
        }
    }


}
